package com.tmc.service.intcar;

import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.tmc.bean.common.CommonResult;
import com.tmc.bean.common.ContextInfo;
import com.tmc.bean.intcar.EthPrice;
import com.tmc.bean.intcar.EthQueryPriceReq;
import com.tmc.bean.intcar.EthQueryPriceResp;
import com.tmc.constant.CacheConstant;
import com.tmc.entity.baseinfo.CarType;
import com.tmc.service.baseinfo.CityServiceImpl;
import com.tmc.service.baseinfo.EthCarTypeServiceImpl;
import com.tmc.service.cache.CacheServiceImpl;
import com.tmc.util.IntcarUtil;
import com.tmc.util.ObjectUtil;
import com.tmc.vendor.intcar.common.ServiceCenter;
import com.tmc.vendor.intcar.common.VendorService;

/**
 * @author zhang
 * @date 2017年12月12日 下午5:29:30 
 */
@Service
public class IntcarQueryPriceServiceImpl {
	
	@Autowired
	private EthCarTypeServiceImpl carTypeService;
	
	@Autowired
	private CityServiceImpl cityService;
	
	@Autowired
	private CacheServiceImpl cache;
	
	private Log log = LogFactory.getLog(IntcarQueryPriceServiceImpl.class);
	
	private static final int THREAD_SIZE = 2;
	
	private static final String THREAD_PRICE_YITU8 = "THREAD_PRICE_YITU8";
	
	private static final String THREAD_PRICE_HERTZ = "THREAD_PRICE_HERTZ";
	
	
	public CommonResult queryPrice(final ContextInfo context, final EthQueryPriceReq req){
		String cacheKey = getCacheKey(context,req);
		if(cache.get(cacheKey) != null){
			return CommonResult.makeSuccess("查询成功！", cache.get(cacheKey));
		}
		CommonResult check = checkReq(req);
		if(!check.isSuccess()){
			return check;
		}
		ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_SIZE);
		CompletionService<Entry<String,Object>> completion = new ExecutorCompletionService<Entry<String,Object>>(threadPool);
		//查询易途8的价格
		completion.submit(new Callable<Entry<String,Object>>() {
			@Override
			public Entry<String, Object> call() throws Exception {
				VendorService service = ServiceCenter.getService("YITU8");
				service.setFromCityIDFromCache(req, cityService.findAllFromCache(context));
				EthQueryPriceResp resp = service.queryPrice(context, req);
				return new AbstractMap.SimpleEntry<String, Object>(THREAD_PRICE_YITU8, resp);
			}
		});
		//查询HERTZ的价格
		completion.submit(new Callable<Entry<String,Object>>() {
			@Override
			public Entry<String, Object> call() throws Exception {
				VendorService service = ServiceCenter.getService("HERTZ");
				service.setFromCityIDFromCache(req, cityService.findAllFromCache(context));
				EthQueryPriceResp resp = service.queryPrice(context, req);
				return new AbstractMap.SimpleEntry<String, Object>(THREAD_PRICE_HERTZ, resp);
			}
		});
		// 获取结果
		Map<String, Object> resultMap = null;
		try {
			resultMap = getThreadResult(completion);
		} catch (Exception e) {
			log.error("查询失败", e);
			return CommonResult.makeFail("查询失败！");
		}
		//关闭线程池
		threadPool.shutdown();
		if(resultMap == null || resultMap.isEmpty()){
			return CommonResult.makeFail("对不起，您选择的服务暂不提供！");
		}
		List<CarType> cacheCarTypes = carTypeService.findAllFromCache();
		//设置价格标识 、并根据条件加价。 并保存在缓存中
		List<EthPrice> prices = this.setPriceMark(resultMap, JSON.toJSONString(req), cacheCarTypes);
		
		//合并所有接口的结果
	 	EthPrice price = mergeResult(prices);
		//加到缓存中，当用户查询参数和之前一样，则直接在缓存中取
		cache.put(cacheKey, price);
		return CommonResult.makeSuccess("", price);
	}
	
	/**
	 * 合并所有接口的结果
	 * 
	 * @author zhang
	 * @param resultMap
	 * @return
	 */
	private EthPrice mergeResult(List<EthPrice> prices) {
		EthPrice price = new EthPrice();
		if(prices.size()<2){
			price = prices.get(0);
		}else{
			// TODO 处理多接口逻辑
		}
		return price;
	}

	/**
	 * 查询价格的参数和价格加到缓存中
	 * 
	 * @author zhang
	 * @param resultMap
	 * @param reqJSON
	 */
	private List<EthPrice> setPriceMark(Map<String, Object> resultMap, String reqJSON, List<CarType> carTypes) {
		if(resultMap == null || resultMap.isEmpty()){
			return null;
		}
		Map<String, String> map = new HashMap<String, String>();
		List<EthPrice> list = new ArrayList<>();
		for (Map.Entry<String, Object> entry  : resultMap.entrySet()) {
			if(entry.getValue() != null){
				EthPrice price= (EthPrice) entry.getValue();
				map.put(price.getPriceMark(), reqJSON);
				// TODO 本地加价逻辑
				price.setAddPrice(0d);
				try {
					ServiceCenter.getService(price.getVendor()).setNativeCarTypeID(new ContextInfo(), price, carTypes);
				} catch (Exception e) {
					log.error("设置本地车型ID出错！", e);
				}
				list.add(price);
			}
		}
		cache.put(CacheConstant.KEY_PRICING_REQUEST_MAP, map);
		for (EthPrice price : list) {
			System.out.println(price.getPriceMark());
			cache.put(price.getPriceMark(), price);
		}
		
		return list;
	}

	private Map<String, Object> getThreadResult(CompletionService<Entry<String, Object>> completion)
			throws Exception {
		Map<String, Object> map = new HashMap<String, Object>();
		for (int i = 0; i < THREAD_SIZE; i++) {
			Entry<String, Object> entry = completion.take().get();
			EthQueryPriceResp value = (EthQueryPriceResp) entry.getValue();
			if(value.isSuccess()){
				map.put(entry.getKey(), value.getPrice());
			}
//			else{
//				map.put(entry.getKey(), null);
//			}
		}
		return map;
	}
	
	public CommonResult checkPrice(ContextInfo context,String priceMark){
		if(ObjectUtil.noText(priceMark)){
			return CommonResult.makeFail("priceMark不能为空！");
		}
		CommonResult cacheResult = IntcarUtil.getPriceFromCache(null, priceMark, cache);
		if(!cacheResult.isSuccess()){
			return cacheResult;
		}
		EthPrice price = (EthPrice)cacheResult.getObj();
		return CommonResult.makeSuccess("", price);
	}
	
	private CommonResult checkReq(EthQueryPriceReq req){
		if(ObjectUtil.noText(req.getUseTime())){
			return CommonResult.makeFail("用车时间不能为空！");
		}
		if(req.getUseDuration() == null){
			return CommonResult.makeFail("用车天数不能为空！");
		}
		if(req.getProductType() == null){
			return CommonResult.makeFail("产品类型不能为空！");
		}
		if(req.getRouteType() == null){
			return CommonResult.makeFail("行程类型不能为空！");
		}
		if(req.getFromCityID() == null){
			return CommonResult.makeFail("出发城市ID不能为空！");
		}
		if(ObjectUtil.noText(req.getFromAddress())){
			return CommonResult.makeFail("出发地址不能为空！");
		}
		if(req.getFromLongitude() == null){
			return CommonResult.makeFail("出发地纬度不能为空！");
		}
		if(req.getFromLongitude() == null){
			return CommonResult.makeFail("出发地纬度不能为空！");
		}
		if(req.getFromLatitude() == null){
			return CommonResult.makeFail("出发地经度不能为空！");
		}
		return CommonResult.makeSuccess();
	}
	
	private String getCacheKey(ContextInfo context, EthQueryPriceReq req){
		return "KEY_PRICING_"+context.getUserId()+JSON.toJSONString(req);
	}
}
